package cn.flying.cloud.oauth.server.configuration.token;

import javax.annotation.Resource;

import java.security.KeyPair;
import java.util.Arrays;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;

import cn.flying.cloud.oauth.server.configuration.details.CustomUserDetailService;

/**
 * Token存储相关配置
 *
 * @author: admin
 * @date: 2023年06月19日 15:11
 * @version: 1.0
 */
@Configuration
public class TokenStoreConfig {

    @Resource
    private JwtTokenEnhancer jwtTokenEnhancer;
    @Resource
    private CustomUserDetailService customUserDetailService;

    /**
     * 配置token存储方式，这里采用Jwt方式
     *
     * @return
     */
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    /**
     * 配置jwt转换器，生成token的转换器，可以实现指定token的生成方式(JWT)和对JWT进行签名，这里采用RSA使用非对称加密算法对token签名
     *
     * @return
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setKeyPair(keyPair());

        // 要注入securityUserDetailService，否则刷新refresh_token时无法获取用户信息
        DefaultUserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter();
        userTokenConverter.setUserDetailsService(customUserDetailService);

        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        accessTokenConverter.setUserTokenConverter(userTokenConverter);

        jwtAccessTokenConverter.setAccessTokenConverter(accessTokenConverter);

        return jwtAccessTokenConverter;
    }

    /**
     * 配置令牌管理
     */
    @Bean
    public AuthorizationServerTokenServices authorizationServerTokenServices(ClientDetailsService clientDetailsService) {
        DefaultTokenServices service = new DefaultTokenServices();
        service.setClientDetailsService(clientDetailsService);
        service.setSupportRefreshToken(true);
        service.setTokenStore(tokenStore());

        //配置JWT的内容增强器
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtTokenEnhancer, jwtAccessTokenConverter()));

        service.setTokenEnhancer(tokenEnhancerChain);
        return service;
    }

    /**
     * 密钥库中获取密钥对(公钥+私钥)，RSA证书jwt.jks
     *
     * @return
     */
    @Bean
    public KeyPair keyPair() {
        //从classpath下的证书中获取秘钥对
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "Rotqwe123,.".toCharArray());
        return keyStoreKeyFactory.getKeyPair("jwt", "Rotqwe123,.".toCharArray());
    }
}
